﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Alipay.AopSdk.AspnetCore;
using Alipay.AopSdk.Core.Request;
using Alipay.AopSdk.Core.Response;
using Casamiel.API.Application;
using Casamiel.API.Application.Commands;
using Casamiel.API.Infrastructure.Filters;
using Casamiel.Application;
using Casamiel.Common;
using Casamiel.Common.Extensions;
using Casamiel.Domain;
using Casamiel.Domain.Entity;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using MediatR;
using Alipay.AopSdk.Core.Domain;
using Casamiel.API.Infrastructure;
using Casamiel.API.Application.Models;
using Microsoft.Extensions.Options;
using Casamiel.API.Application.Services;
using Newtonsoft.Json.Linq;
using Casamiel.Application.Commands;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

namespace Casamiel.API.Controllers.V1
{

    /// <summary>
    /// 
    /// </summary>
    public class AlipayMiniAuthReq
    {
        /// <summary>
        /// 
        /// </summary>
        public   string Code { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public string AppId { get; set; }
    }

    /// <summary>
    /// 支付宝小程序接口
    /// </summary>
    [Produces("application/json")]
    [ApiVersion("1.0")]
    [Route("api/v{api-version:apiVersion}/[controller]")]
    [Authorize]
    [ApiController]
    [EnableCors("any")]
    public class AlipayMiniAppController : BaseController
    {
        private readonly IMediator _mediator;
        private readonly IAlipayMiniAppService _alipayMiniAppService;
        private readonly AlipayService _alipayService;
        private readonly NLog.ILogger logger = NLog.LogManager.GetLogger("WxAppService");
        private readonly IUserLogService _userLog;
        private readonly IMemberService _memberService;
        private readonly IMobileCheckCode _mobileCheckCode;
        private readonly IMemberCardService _memberCardService;
        private readonly CasamielSettings _settings;
        private readonly IPayGateWayService _payGateWayService;
        private readonly IPaymentService _paymentService;
        private readonly IIcApiService _iicApiService;
        private readonly IStoreService _storeService;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="alipayService"></param>
        /// <param name="alipayMiniAppService"></param>
        /// <param name="userLog"></param>
        /// <param name="memberService"></param>
        /// <param name="mobileCheckCodeService"></param>
        /// <param name="mediator"></param>
        /// <param name="memberCardService"></param>
        /// <param name="payGateWayService"></param>
        /// <param name="settings"></param>
        /// <param name="paymentService"></param>
        /// <param name="icApiService"></param>
        /// <param name="storeService"></param>
        public AlipayMiniAppController(AlipayService alipayService, IAlipayMiniAppService alipayMiniAppService, IUserLogService userLog, IMemberService memberService,
            IMobileCheckCode mobileCheckCodeService, IMediator mediator, IMemberCardService memberCardService, IPayGateWayService payGateWayService,
            IOptionsSnapshot<CasamielSettings> settings, IPaymentService paymentService, IIcApiService icApiService, IStoreService storeService
           )
        {
            if (settings is null) {
                throw new ArgumentNullException(nameof(settings));
            }

            _alipayService = alipayService;
            _alipayMiniAppService = alipayMiniAppService;
            _userLog = userLog;
            _memberService = memberService;
            _mobileCheckCode = mobileCheckCodeService;
            _mediator = mediator;
            _memberCardService = memberCardService;
            _payGateWayService = payGateWayService;
            _settings = settings.Value;
            _paymentService = paymentService;
            _iicApiService = icApiService;
            _storeService = storeService;
        }


        /// <summary>
        /// 授权登陆
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("[action]")]
        public async Task<IActionResult> Auth([FromBody] AlipayMiniAuthReq req)
        {
            Console.WriteLine($"{ base.LoginInfo}");
            var d = GetShareResponse(req.Code, "");
            if (d != null) {
                if (d.Code == "10000") {
                    var entity = await _alipayMiniAppService.FindAsync(req.AppId, d.UserId.ToInt64(0)).ConfigureAwait(false);
                    if (entity == null) {
                        entity = new Domain.Entity.AlipayMiniOpenId {
                            AppId = req.AppId, UserId = d.UserId.ToInt64(0),
                            CreateTime = DateTime.Now
                        };
                        await _alipayMiniAppService.AddAsync(entity).ConfigureAwait(false);
 }
                    if (string.IsNullOrEmpty(entity.Mobile)) {
                        return new JsonResult(new { code = 0, id = entity.ID, isBind = false });
                    }
                    var loginInfo = base.LoginInfo;
                    var loginType = loginInfo.Item1;
                    var command = new CreateMemberAccessTokenComand(entity.Mobile, loginType, "") { RequestUrl = Request.GetShortUri(), UserIP = Request.GetUserIp() };
                    var tokens = await _mediator.Send(command).ConfigureAwait(false);

                    return new JsonResult(new { code = 0, id = entity.ID, isBind = true, data = tokens });
                }
                return Ok(new { code = 9999, msg = d.Msg });
            }
            return Ok(new { code = 9999,msg="" });
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("[action]")]
        public async Task<IActionResult> BindMobile([FromBody]Application.Models.WxAppBindMobileReq data)
        {
            if (data == null) {
                throw new ArgumentNullException(nameof(data));
            }
            logger.Trace($"BindMobile:{JsonConvert.SerializeObject(data)}");
            ConsoleHelper.DoLog(data, Request);
            if (data.id == 0) {
                logger.Error($"BindMobile-----ip:{Request.GetUserIp()}id不存在");

                var json = new JsonErrorResponse {
                    code = 999,
                    msg = "id不存在"
                };
                return new JsonResult(json);
            }
            var sucess = _mobileCheckCode.CheckCode(data.mobile, data.yzm, false);

            if (sucess["Success"].ToString().ToLower(CultureInfo.CurrentCulture) == "false") {
                return new JsonResult(new { code = "-2", msg = sucess["msg"].ToString() });
            }
            var member = await _memberService.FindAsync<ICasaMielSession>(data.mobile).ConfigureAwait(false);
            if (member == null) {
                member = new Member { Mobile = data.mobile, CreateDate = DateTime.Now, LastLoginDate = DateTime.Now, Source = 2 };
                try {
                    await _memberService.AddAsync<ICasaMielSession>(member).ConfigureAwait(false);
                } catch (SqlException ex) {
                    if (ex.Number == 2627) {
                        member = await _memberService.FindAsync<ICasaMielSession>(data.mobile).ConfigureAwait(false);
                        member.LastLoginDate = DateTime.Now;
                        await _memberService.UpdateLastLoginDateAsync<ICasaMielSession>(member.ID, DateTime.Now).ConfigureAwait(false);
                    }
                }
            } else {
                member.LastLoginDate = DateTime.Now;
                await _memberService.UpdateLastLoginDateAsync<ICasaMielSession>(member.ID, DateTime.Now).ConfigureAwait(false);
                //await _memberService.UpdateAsync<ICasaMielSession>(member).ConfigureAwait(false);
            }
            var userinfo = await _alipayMiniAppService.FindAsync(data.id).ConfigureAwait(false);
            if (userinfo == null) {
                var json = new JsonErrorResponse {
                    code = 999,
                    msg = "很抱歉，出错了"
                };
                return new JsonResult(json);
            }

            userinfo.Mobile = data.mobile;
            userinfo.UpdateTime = DateTime.Now;
            // Console.WriteLine($"updatewxopeid:{JsonConvert.SerializeObject(userinfo)}");
            await _alipayMiniAppService.UpdateAsync(userinfo).ConfigureAwait(false);
            //if (!string.IsNullOrEmpty(data.Scene)) {
            //    Regex reg = new Regex(@"shopid=(\d*)");
            //    Match match = reg.Match(data.Scene);
            //    string value = match.Groups[1].Value;
            //    if (!string.IsNullOrEmpty(value)) {
            //        var command = new CreateWxExtensionCommand(userinfo, value.ToInt32(0));
            //        await _mediator.Send(command).ConfigureAwait(false);
            //    }

            //} else {
            //    var command = new CreateWxExtensionCommand(userinfo, 0);
            //    await _mediator.Send(command).ConfigureAwait(false);
            //}

            var loginInfo = base.LoginInfo;
            var loginType = loginInfo.Item1;
            var command = new CreateMemberAccessTokenComand(data.mobile, loginInfo.Item1, "") { RequestUrl = Request.GetShortUri(), UserIP = Request.GetUserIp() };
            var tokens = await _mediator.Send(command).ConfigureAwait(false);

            //var tokens = _tokenProvider.GenerateToken(data.mobile);
            //var userAgent = string.IsNullOrEmpty(Request.Headers["User-Agent"].ToString()) ? Request.Headers["UserAgent"].ToString() : Request.Headers["User-Agent"].ToString();
            //int loginType = userAgent.Contains("CASAMIEL", StringComparison.CurrentCulture) ? 1 : 2;
            //if (userAgent.Contains("MicroMessenger", StringComparison.CurrentCulture)) {
            //    loginType = 3;
            //}

            
            string cardno = "";
            var list = await _memberCardService .GetListAsync<ICasaMielSession>(data.mobile).ConfigureAwait(false);
            if (list.Count > 0) {
                var cardinfo = list.FirstOrDefault(c => c.IsBind == true);
                if (cardinfo != null) {
                    cardno = cardinfo.CardNO;
                }
            }
            var logdata = new UserLog { Url = Request.GetShortUri(), OPInfo = $"用户登陆", OPTime = DateTime.Now, UserName = data.mobile, UserIP = Request.GetUserIp() };
            await _mediator.Publish(new UserLogNoticeCommand(logdata)).ConfigureAwait(false);
            //await _userLog.AddAsync<ICasaMielSession>(logdata).ConfigureAwait(false);
            //string key = Constant.TOKEN_PREFIX + data.mobile + "_" + loginType;
            //_cacheService.Remove(key);

            var memberdata = new { Mobile = member.Mobile, Nick = member.Nick, Birthday = member.Birthday, Sex = member.Sex, TrueName = member.TrueName, Email = member.Email, cardno = cardno };
            return new JsonResult(new { code = 0, data = tokens, member = memberdata });
        }

        /// <summary>
        /// 充值
        /// </summary>
        /// <param name="data"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("[Action]")]
        [TypeFilterAttribute(typeof(CheckTokenAttribute))]
        public async Task<IActionResult> PaymentRequest([FromBody] PaymentReq data, [FromHeader(Name = "u-token")] string token)
        {
             if (data == null) {
                throw new ArgumentNullException(nameof(data));
            }
          string outTradeNo = "C" + DateTime.Now.ToString("yyyyMMddHHmmssffff", CultureInfo.CurrentCulture);

        var content = "";
            var mobile = MemberHelper.GetMobile(token);
            if (_settings.IsTest) {
                var tester = await _paymentService.GetAllTesterAsync<ICasaMielSession>().ConfigureAwait(false);
                if (tester.Where(a => a.Mobile == mobile).Count() == 1) {
                    var tentity = tester.Where(a => a.Mobile == mobile).SingleOrDefault();
                    data.chargemoney = tentity.chargemoney;
                }
            }

            if (data.operationMethod == 1) {
                var list =  await _memberCardService.GetListAsync<ICasaMielSession>(mobile).ConfigureAwait(false);
                
                var mcard = list.FirstOrDefault(a => a.IsBind == true && a.CardNO == data.billNO);
                // var mcard = _cacheService.Get<MemberCard>("c_" + token);
                if (mcard != null) {
                    var a = await _iicApiService.GetCardBalance(data.billNO,$"{LoginInfo.Item3}099".ToInt32(0)).ConfigureAwait(false);
                    var rnt = JsonConvert.DeserializeObject<JObject>(a.content);
                    if (a.code == 0) {
                        var je = Convert.ToDouble(rnt["totalmoney"].ToString(), CultureInfo.CurrentCulture);
                        if ((je + data.chargemoney) > 2500) {
                            return new JsonResult(new { code = -1, content = "", msg = $"最多还能充值{(2500 - je).ToString("C2", CultureInfo.CurrentCulture)}" });
                        }
                    } else {
                        if (data.chargemoney > 2500) {
                            return new JsonResult(new { code = -1, content = "", msg = $"最多还能充值{(2500).ToString("C2", CultureInfo.CurrentCulture)}" });
                        }
                    }
                } else {
                    return new JsonResult(new { code = -1, content = "", msg = "无此卡" });
                }
            }
            var shopname = "";
            if (data.shopId.HasValue && data.shopId > 0) {
                var store = await _storeService.GetByRelationIdAsync<ICasaMielSession>(data.shopId.Value).ConfigureAwait(false);
                if (store != null) {
                    shopname = store.StoreName;
                }
            }
            switch (data.paytype) {
                case 2:
                    content = _payGateWayService.CreateAlipayOrder(outTradeNo, data.chargemoney, shopname, (shopname.Length > 0 ? data.shopId.Value.ToString(CultureInfo.CurrentCulture) : ""));// CreateAlipayOrder(data);
                    data.summary = "app支付宝支付";
                    break;
                case 1:
                    content = _payGateWayService.CreateWechatpayOrder(outTradeNo, data.chargemoney, shopname, (shopname.Length > 0 ? data.shopId.Value.ToString(CultureInfo.CurrentCulture) : ""));// CreateWechatpayOrder(data);
                    data.summary = "app微信支付";
                    break;
                case 6:
                    if (data.id <= 0) {
                        return Ok(new { code = 999, msg = "id不对" });
                    }
                    var entity = await _alipayMiniAppService.FindAsync(data.id).ConfigureAwait(false);
                    if (entity == null) {
                        return Ok(new { code = 999, msg = "id不对" });
                    }
                    content = _payGateWayService.CreateAlipayAppletOrder($"{entity.UserId}",outTradeNo, data.chargemoney, shopname, (shopname.Length > 0 ? data.shopId.Value.ToString(CultureInfo.CurrentCulture) : ""));// CreateWechatpayOrder(data);
                    data.summary = "支付宝小程序支付";
                    break;
                default:
                    break;
            }
            var payment = new PaymentRecord() {
                Mobile = data.mobile,
                BillNO = data.billNO,
                OperationMethod = 1,
                Amount = data.chargemoney,
                CreateTime = DateTime.Now,
                ShopId = data.shopId,
                TradeNo = outTradeNo,
                PayMethod = data.paytype,
                Remark = data.summary
            };
            await _paymentService.AddAsync<ICasaMielSession>(payment).ConfigureAwait(false);
            //  var ad = await _paymentRecordRepository.UnitOfWork.SaveEntitiesAsync();
            return new JsonResult(new { code = 0, content = content });
        }
        
       
        private AlipayUserInfoShareResponse GetShareResponse(string auth_code,string appid)
        {
           Console.WriteLine($"{ _alipayService.Options.AppId}");


            var alipaySystemOauthTokenRequest = new AlipaySystemOauthTokenRequest {
                Code = auth_code,
                GrantType = "authorization_code"
            };
            var oauthTokenResponse = _alipayService.Execute(alipaySystemOauthTokenRequest);

            if (!oauthTokenResponse.IsError) {
                Console.WriteLine($"{oauthTokenResponse.AccessToken}");
                AlipayUserInfoShareRequest requestUser = new AlipayUserInfoShareRequest();
                

                AlipayUserInfoShareResponse userinfoShareResponse = _alipayService.Execute(requestUser, oauthTokenResponse.AccessToken);
                return userinfoShareResponse;
            }
            return null;
        }
    }
}
